# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# File       : handle_extract.py
# Time       ：2022/6/3 13:25
# Author     ：周豪权
"""
import copy
import jsonpath
import yaml
from dataclasses  import asdict
from string import Template

from debugs.debug_talk import DebugTalk
from utils.handle_model import CaseInfo
from utils.handle_yaml import YamlData
from utils.handle_request import logger
import re


class ExtractUtil:

    #提取变量
    def extract(self,response,var_name:str,attr_name:str,expr:str,index:int):
        #1.深拷贝一个response
        resp = copy.deepcopy(response)
        #2.把json（）改成一个属性
        try:
            resp.json = resp.json()
        except Exception:
            resp.json = {"msg":"response is not json"}
        # print(resp.json, type(resp.json))
        #3.通过属性反射获取到属性的数据
        data = getattr(resp,attr_name)
        #判断提取方式
        if expr.startswith("$"): #jsonpath提取
            lis = jsonpath.jsonpath(dict(data),expr)
        else:
            lis = re.findall(expr,data)

        #通过下标取值
        if lis:
            var_value = lis[index]
        else:
            var_value = "not extract data"

        #把提取的数据写入extract.yaml
        YamlData('./extract.yaml').a_data({var_name:var_value})

    #使用变量(替换)
    def change(self,caseinfo: CaseInfo):
        #1.把CaseInfo改成一个字典(dataclass 的方法)，然后转换成一个字符串
        # asdict(caseinfo)
        yaml_str = yaml.dump(asdict(caseinfo))
        print(yaml_str)
        #2.替换
        # new_str = Template(str).safe_substitute(YamlData('./extract.yaml').r_data)
        new_yaml_str = ExtractUtil().hot_load_replace(yaml_str)
        print(new_yaml_str)
        #3.转回Caseinfo对象
        # yaml.safe_load(new_yaml_str)
        ci_obj = CaseInfo(**yaml.safe_load(new_yaml_str))
        return ci_obj

    #热加载
    def hot_load_replace(self,yaml_str):
        #定义正则
        #${函数名(变量名1,变量名2...)}
        #python双斜杠对$转义，表示自己本身；{}可以不转义，也可以进行转义，在正则不加也可以
        regxp = "\\${(.*?)\\((.*?)\\)}"
        #通过正则匹配yaml文件里面的表达式
        fun_list = re.findall(regxp,yaml_str)
        for f in fun_list:
            if f[1] == '':  #没有参数
                new_value = getattr(DebugTalk(),f[0])()
            else:    #有参数,可能一个，可能两个
                new_value= getattr(DebugTalk(),f[0])(*f[1].split(","))
            #判断如果是数字类型的字符串，那么加上单引号
            try:
                if isinstance(new_value,str):
                    int(new_value)
                    new_value = "'"+new_value+"'"
            except Exception:
                pass
            #拼接旧值
            old_value = "${"+f[0]+"("+f[1]+")}"
            #把旧的字符串替换成新的字符串
            yaml_str = yaml_str.replace(old_value,str(new_value))
        return yaml_str

    #断言变量提取
    def ass_ert(self,response,attr_name:str,expr:str,index = None):
        #通过属性反射获取到属性的数据
        data = getattr(response,attr_name)
        #判断提取方式是否复合yaml规范
        if expr.startswith("$"): #jsonpath提取
            lis = jsonpath.jsonpath(dict(data),expr)
        else:
            logger.error("YAML断言提取格式不符合框架规则\n")
            # 抛出异常
            raise Exception("YAML格式不符合框架规则！")

        #通过下标取值
        #不能用if index：  #这个如果index这个变量为数字的话，会走else那边的程序
        if not index is None:
            if lis:
                var_value = lis[index]
            else:
                var_value = "not extract data"
        else:
            var_value = lis

        return var_value






#单元测试
class Test:
    dic = {'metadata': {'path': '/api/v1/user/login', 'httpStatusCode': 200, 'httpStatus': 'OK', 'message': 'POST /api/v1/user/login [200] OK', 'timestamp': 1685774365}, 'code': 200, 'data': 'eyJhbGciOiJIUzUxMiJ9.eyJpY19sb2dpbl91c2VyX2tleSI6IjdkZDljYmI0LTc5N2YtNDk3Yi1hMDk0LWZmMmYyOWYxNjJkOSJ9.lxnRa9BwabOJ5MkOfzF0QhwczbcdJikVcNefz7WFApp-H_1e3xykVVMLLDsO42AA9HvWbLvhgehrZAeZMd-43Q', 'msg': None}




if __name__ == '__main__':
    test = Test()
    ExtractUtil().extract(test,'token','dic','$.data',0)